package com.laijiale.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.laijiale.constant.ML;
import com.laijiale.dto.RoleInsertDTO;
import com.laijiale.dto.RolePageDTO;
import com.laijiale.dto.RoleUpdateDTO;
import com.laijiale.entity.Menu;
import com.laijiale.entity.Role;
import com.laijiale.entity.RoleMenu;
import com.laijiale.exception.ServiceException;
import com.laijiale.mapper.RoleMenuMapper;
import com.laijiale.vo.MenuSimpleListVO;
import com.laijiale.vo.RoleSimpleListVO;
import com.mybatisflex.core.query.QueryChain;
import com.mybatisflex.core.update.UpdateChain;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.laijiale.entity.Role;
import com.laijiale.mapper.RoleMapper;
import com.laijiale.service.RoleService;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import static com.laijiale.entity.table.MenuTableDef.MENU;
import static com.laijiale.entity.table.RoleMenuTableDef.ROLE_MENU;
import static com.laijiale.entity.table.RoleTableDef.ROLE;


/**
 *  服务层实现。
 *
 * @author laijiale
 * @since 2024-12-22
 */
@Service
@CacheConfig(cacheNames = "role")
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role>  implements RoleService {
    @Autowired
    private  RoleMenuMapper roleMenuMapper;


    @CacheEvict(allEntries = true)
    @Override
    public boolean insert(RoleInsertDTO dto) {
        Role role = BeanUtil.copyProperties(dto, Role.class);

        //标题不能重复
        if (QueryChain.of(mapper)
                .where(ROLE.TITLE.eq(role.getTitle()))
                .exists()) {
            throw new ServiceException("角色标题已存在");
        }
        role.setCreated(LocalDateTime.now());
        role.setUpdated(LocalDateTime.now());
        return mapper.insert(role) > 0;

    }

    @Cacheable(key = "#p0", condition = "#p0 != null", unless = "#result == null")
    @Override
    public Role select(Long id) {
        return QueryChain.of(mapper)
                .where(ROLE.ID.eq(id))
                .withRelations()
                .one();
    }
    @Cacheable(key = "#root.methodName",
            unless = "#result == null")
    @Override
    public List<RoleSimpleListVO> simpleList() {
        //查询所有菜单
        List<Role> roles =QueryChain.of(mapper).orderBy(ROLE.IDX.asc(),ROLE.ID.desc()
        ).withRelations().list();
        //封装VO
        List<RoleSimpleListVO> roleSimpleListVOS=new ArrayList<>();
        roles.forEach(role -> {
            RoleSimpleListVO roleSimpleListVO=BeanUtil.copyProperties(role,RoleSimpleListVO.class);

            roleSimpleListVOS.add(roleSimpleListVO);
        });

        return roleSimpleListVOS;
    }



    @CacheEvict(allEntries = true)
    @Override
    public boolean update(RoleUpdateDTO dto) {
        //标题查重
        if (QueryChain.of(mapper).where(ROLE.TITLE.eq(dto.getTitle())).exists()) {
            throw new ServiceException("角色标题已存在");
        }
        //组装 entity 实体类
        Role role = BeanUtil.copyProperties(dto, Role.class);
        role.setUpdated(LocalDateTime.now());
        return mapper.update(role) > 0;
    }

    @CacheEvict(allEntries = true)
    @Override
    public boolean delete(Long id) {
        return UpdateChain.of(mapper)
                .where(ROLE.ID.eq(id)).remove();

    }

    @CacheEvict(allEntries = true)
    @Override
    public boolean deleteBatch(List<Long> ids) {
        return UpdateChain.of(mapper).where(ROLE.ID.in(ids)).remove();
    }




    @Cacheable(key = "#root.methodName + ':' + #p0.toString()", unless = "#result == null")
    @Override
    public Page<Role> page(RolePageDTO dto) {
        QueryChain<Role> queryChain = QueryChain.of(mapper)
                .orderBy(ROLE.IDX.asc(), ROLE.ID.desc());
        if (ObjectUtil.isNotNull(dto.getTitle())) {
            queryChain.where(ROLE.TITLE.like(dto.getTitle()));
        }
        return queryChain.withRelations()
                .page(new Page<>(dto.getPageNum(), dto.getPageSize()));
    }

    @Cacheable(key = "#root.methodName + ':' + #p0",
            condition = "#p0 != null",
            unless = "#result == null")
    @Override
    public List<Long> listMenuIds(Long id) {
        return QueryChain.of(RoleMenu.class).select(ROLE_MENU.FK_MENU_ID)
                .where(ROLE_MENU.FK_ROLE_ID.eq(id))
                .objListAs(Long.class);


    }

    @CacheEvict(allEntries = true)
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean updateMenus(RoleUpdateDTO dto) {
        Long roleId = dto.getId();
        List<Long> menuIds = dto.getMenuIds();
        //在中间表中删除该角色的全部菜单记录
        UpdateChain.of(roleMenuMapper)
                .where(ROLE_MENU.FK_ROLE_ID.eq(roleId))
                .remove();
        //新菜单列表为空，直接返回即可
        if (menuIds.isEmpty()) {
            return true;
        }
            //在中间表中批量添加该角色的新菜单记录
            List<RoleMenu> roleMenus = new ArrayList<>();
            for (Long menuId : menuIds) {
                RoleMenu roleMenu = new RoleMenu();
                roleMenu.setFkRoleId(roleId);
                roleMenu.setFkMenuId(menuId);
                roleMenu.setCreated(LocalDateTime.now());
                roleMenu.setUpdated(LocalDateTime.now());
                roleMenus.add(roleMenu);
            }
            return roleMenuMapper.insertBatch(roleMenus) == menuIds.size();

        }
    }


